package org.bilinc.gz001;

import org.apache.commons.lang.math.NumberUtils;
import org.bilinc.gz001.dao.*;
import org.bilinc.gz001.dao.recover.RecoverCalendar;
import org.bilinc.gz001.entity.City;
import org.bilinc.gz001.entity.Position;
import org.bilinc.gz001.entity.Resource;
import org.bilinc.gz001.hibernateUtil.HibernateUtil;
import org.bilinc.gz001.service.WorkingDataService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;

@Component
public class ModelService {

    @Autowired
    HibernateUtil hibernateUtil;

    @Autowired
    PositionDao positionDao;

    @Autowired
    ResourceDao resourceDao;

    @Autowired
    WorkingDataDao workingDataDao;

    @Autowired
    WorkingDataService workingDataService;

    @Autowired
    CityDao cityDao;

    @Autowired
    MonthDao monthDao;

    @Autowired
    GazConstantDao gazConstantDao;

    @Autowired
    RecoverCalendar recoverCalendar;


    UiTableData leftTableData = new UiTableData();
    UiTableData rightTableData = new UiTableData();
    UiTableData footerTableData = new UiTableData();

    Object[][] leftArrayTableData;
    Object[][] rightArrayTableData;
    Object[][] footerArrayTableData;

    UiTableData getLeftTableData() {
        return leftTableData;
    }

    ModelService() {
    }

    public void initialize() {
        buildLeftRightFooterTableRows();
        leftTableData.setColumns(Utils.WORKED_HEADER);
    }

    /*Использовать этот метод для получения первоначальных данных от модели
     Внимание! Активно юзает БД*/
    public void buildLeftRightFooterTableRows() {
        leftTableData.clear();
        rightTableData.clear();

        List<Position> positions = positionDao.getAll();
        for (Position position : positions) {
            List<Resource> resources = resourceDao.getListOfPosition(position);
            ArrayList<String> temp = new ArrayList<String>();
            temp.add("");
            temp.add(position.getPosition());
            leftTableData.addRow(temp);
            ArrayList<String> temp2 = new ArrayList<String>();
            temp2.add("");
            rightTableData.addRow(temp2);
            for (Resource resource: resources) {
                List<String> data = workingDataDao.getYearWorkingDataByResource(resource);
                rightTableData.addRow(data);

                ArrayList<String> temp3 = new ArrayList<String>();
                addDataFromResourceToRow(resource,temp3);
                temp3.addAll(workingDataService.countLeftfields(data));
                leftTableData.addRow(temp3);
            }
        }

        workingDataService.countFooterRows(leftTableData, rightTableData, footerTableData);
        leftArrayTableData = Utils.convertListListToArrayArray(leftTableData);
        rightArrayTableData = Utils.convertListListToArrayArray(rightTableData);
        footerArrayTableData = Utils.convertListListToArrayArray(footerTableData);
        //TODO убарть эти массивы к чертям
    }

    //Для построения строки которую отдаем во вью
    public void addDataFromResourceToRow(Resource res, List<String> row) {
        if (res.getTabNumber() != null) {
            row.add(res.getTabNumber());
        } else {
            row.add("");
        }
        if (res.getCity() != null) {
            row.add(res.getCity().getCity());
        } else {
            row.add("");
        }
        if (res.getFullName() != null) {
            row.add(res.getFullName());
        } else {
            row.add("");
        }
    }

    /*Событие от вьюхи - поменяли что-то в календаре*/
    public Object[] onRightTableDataSet(int monthNum, int dayNum, int row, int column, Object value, Object tabN) {
        if (Application.DEBUG) {
            System.out.println(
                            "month=" + monthNum +
                            " day=" + dayNum +
                            " row=" + row +
                            " col=" + column +
                            " val=" + value +
                            " tabN=" + tabN);
        }

        try{
            rightTableData.setCell(String.valueOf(value), row, column);
        } catch (IndexOutOfBoundsException e) {
            recoverCalendar.emergencyRecoverCalendarFromCorrupted(2013, monthNum, dayNum, String.valueOf(tabN));
        }
        workingDataService.countFooterRows(leftTableData, rightTableData, footerTableData);  //TODO рефакторинг!
        List<String> columnData = new ArrayList<String>();
        for (int i = 0; i < 11; i++) {
            columnData.add(footerTableData.getCell(i, column));
        }

        monthDao.updateDataByDateAndResource(2013, monthNum, dayNum, String.valueOf(tabN), String.valueOf(value));
        List<String> tableRow = new ArrayList<String>();
        List<String> leftCountedValues = workingDataService.countLeftfields(rightTableData.getRow(row));

        Resource res = resourceDao.findByTanelNumber(String.valueOf(tabN));
        addDataFromResourceToRow(res,tableRow);
        tableRow.addAll(leftCountedValues);
        leftTableData.setRow(tableRow, row);

        leftArrayTableData = Utils.convertListListToArrayArray(leftTableData);
        rightArrayTableData = Utils.convertListListToArrayArray(rightTableData);
        footerArrayTableData = Utils.convertListListToArrayArray(footerTableData);

        return new Object[] {leftCountedValues, columnData};
    }

    /*Событие от вьюхи - удалили чела*/
    public void onRowDelete(final int row, final Object tabN) {
        if (Application.DEBUG) {
            System.out.println(
                            "row=" + row +
                            " tabN=" + tabN);
        }

        leftTableData.removeRow(row);
        rightTableData.removeRow(row);
        resourceDao.removeByTanelNumber(String.valueOf(tabN));
        workingDataService.countFooterRows(leftTableData, rightTableData, footerTableData);
        leftArrayTableData = Utils.convertListListToArrayArray(leftTableData);
        rightArrayTableData = Utils.convertListListToArrayArray(rightTableData);
        footerArrayTableData = Utils.convertListListToArrayArray(footerTableData);
    }

    /*Событие от вьюхи - добавили чела*/
    public void onRowAdd(String city, String name, String positionName, String tabNumber, int rows) {

        Integer row = fingPositionInTable(positionName);
        if (row == null){
            throw new IllegalStateException("Должна быть такая позиция!");
        }

        Resource res = new Resource();
        res.setCity(cityDao.findByName(city));
        res.setFullName(name);
        res.setPosition(positionDao.findByName(positionName));
        res.setTabNumber(tabNumber);
        resourceDao.save(res);
        monthDao.addCalendarForResource(res);

        List<String> calendarData = workingDataDao.getYearWorkingDataByResource(res);
        List<String> leftCountedFields = workingDataService.countLeftfields(calendarData);
        List<String> tableRow = new ArrayList<String>();

        addDataFromResourceToRow(res, tableRow);
        tableRow.addAll(leftCountedFields);

        leftTableData.insertRow(row, tableRow);
        rightTableData.insertRow(row, calendarData);
        workingDataService.countFooterRows(leftTableData, rightTableData, footerTableData);

        leftArrayTableData = Utils.convertListListToArrayArray(leftTableData);
        rightArrayTableData = Utils.convertListListToArrayArray(rightTableData);
        footerArrayTableData = Utils.convertListListToArrayArray(footerTableData);  //TODO убрать

    }

    private Integer fingPositionInTable(String position) {
        for (int rows = 0; rows < leftTableData.getRowCount(); rows++) {
            if ("".equals(leftTableData.getCell(rows, 0)) && position.equals(leftTableData.getCell(rows, 1))) {
                return rows;
            }
        }
        return null;
    }

    public Object[][] getLeftArrayTableData() {
        return leftArrayTableData;
    }

    public void setLeftArrayTableData(Object[][] leftArrayTableData) {
        this.leftArrayTableData = leftArrayTableData;
    }

    public Object[][] getRightArrayTableData() {
        return rightArrayTableData;
    }

    public void setRightArrayTableData(Object[][] rightArrayTableData) {
        this.rightArrayTableData = rightArrayTableData;
    }

    public Object[][] getFooterArrayTableData() {
        return footerArrayTableData;
    }

    public void setFooterArrayTableData(Object[][] footerArrayTableData) {
        this.footerArrayTableData = footerArrayTableData;
    }

    public Double getNO() {
        return gazConstantDao.getNO();
    }

    public void setNO(Double NO) {
        gazConstantDao.setNO(NO);
    }

    public Integer getGNV() {
        return gazConstantDao.getGNV();
    }

    public void setGVN(Integer GNV) {
        gazConstantDao.setGNV(GNV);
    }

    public Position findPositionOfResourceByTabNomer(String tabNomer) {
        return resourceDao.findByTanelNumber(tabNomer).getPosition();
    }

    public List<Position> getAllPositions(){
        return positionDao.getAll();
    }

    public List<City> getAllCities(){
        return cityDao.getAll();
    }
    public HibernateUtil getHibernateUtil() {
        return hibernateUtil;
    }


    public boolean isTabelNumberExists(String tabNumber) {
        return resourceDao.findByTanelNumber(tabNumber) == null;
    }
}
